package edu.sctu.zhoudie.mouth201506.day20150602;

/**
 * Created by Administrator on 2015-06-07.
 */
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class Clock extends Applet {
        private final Panel pnlTop = new Panel();
        private final Panel pnlBot = new Panel();
        private final Label lblDate = new Label();
        private final Label lblTime = new Label();
        private final Label lblWatch = new Label();
        private final Button btnGo = new Button("开始");
        private final Button btnReset = new Button("重置");
        private final Label lblSplit = new Label();
        private final Button btnSplit = new Button("定点");
        private final Button btnSplitReset = new Button("定点重置");
        private final Button btnLapAdd = new Button("冲线");
        private final Button btnLapReset = new Button("冲线重置");
        private final java.awt.List lstLaps = new java.awt.List();
        private final UpdateClockThread ucThread = new UpdateClockThread();
        private final StopwatchThread swThread = new StopwatchThread();

        private class btnGoListener implements ActionListener {
            public void actionPerformed(ActionEvent e) {
                if ((btnGo.getLabel().equals("开始")) ||
                        (btnGo.getLabel().equals("继续"))) {
                    // Start the clock!
                    swThread.go();
                    btnGo.setLabel("停止");
                    btnGo.setBackground(Color.red);
                } else if (btnGo.getLabel().equals("停止")) {
                    // Stop the clock!
                    swThread.noGo();
                    btnGo.setLabel("继续");
                    btnGo.setBackground(Color.green);
                }
            }
        }

        private class btnResetListener implements ActionListener {
            /** Actually run when the button gets clicked.
             *@param e The event
             */
            public void actionPerformed(ActionEvent e) {
                swThread.reset();
                btnGo.setLabel("开始");
                btnGo.setBackground(Color.green);
            }
        }

        /** Listens to the Split button.
         * @version CS2136 - Term D'00 - Assignment 5
         * @author Peter Cooper Jr.
         */
        private class btnSplitListener implements ActionListener {
            /** Actually run when the button gets clicked.
             *@param e The event
             */
            public void actionPerformed(ActionEvent e) {
                lblSplit.setText(lblWatch.getText());
            }
        }

        /** Listens to the Split Reset button.
         * @version CS2136 - Term D'00 - Assignment 5
         * @author Peter Cooper Jr.
         */
        private class btnSplitResetListener implements ActionListener {
            /** Actually run when the button gets clicked.
             *@param e The event
             */
            public void actionPerformed(ActionEvent e) {
                lblSplit.setText("");
            }
        }

        /** Listens to the Lap Add button.
         * @version CS2136 - Term D'00 - Assignment 5
         * @author Peter Cooper Jr.
         */
        private class btnLapAddListener implements ActionListener {
            /** Actually run when the button gets clicked.
             *@param e The event
             */
            public void actionPerformed(ActionEvent e) {
                swThread.addLap();
            }
        }

        /** Listens to the Lap Reset button.
         * @version CS2136 - Term D'00 - Assignment 5
         * @author Peter Cooper Jr.
         */
        private class btnLapResetListener implements ActionListener {
            /** Actually run when the button gets clicked.
             *@param e The event
             */
            public void actionPerformed(ActionEvent e) {
                swThread.resetLap();
            }
        }

        /** A thread that updates the current date & time.
         * @version CS2136 - Term D'00 - Assignment 5
         * @author Peter Cooper Jr.
         */
        private class UpdateClockThread extends Thread {
            /** The actual work of the thread.
             */
            public void run() {
                while (true) {
                    Calendar now = Calendar.getInstance();
                    String month = Integer.toString(now.get(Calendar.MONTH)+1);
                    String date = Integer.toString(now.get(Calendar.DAY_OF_MONTH));
                    String year = Integer.toString(now.get(Calendar.YEAR));
                    String hour = Integer.toString(now.get(Calendar.HOUR));
                    if (hour.equals("0")) hour = "12";
                    String minute = Integer.toString(now.get(Calendar.MINUTE));
                    if (minute.length() == 1) minute = "0" + minute;
                    String second = Integer.toString(now.get(Calendar.SECOND));
                    if (second.length() == 1) second = "0" + second;
                    String ampm = now.get(Calendar.AM_PM) == Calendar.AM
                            ? "AM" : "PM";

                    lblDate.setText(month + "/" + date + "/" + year);
                    lblTime.setText(hour + ":" + minute + ":" + second
                            + " " + ampm);
                    try {
                        sleep(500);
                    } catch (InterruptedException e) {}
                }
            }
        }

        private class StopwatchThread extends Thread {
            /** Whether or not stopwatch is running. */
            private boolean going = false;
            /** Stores elapsed milliseconds of previous runs. */
            private long prevElapsed = 0;
            /** Stores beginning time of this run. */
            private Date startDate = new Date();
            /** Current lap number. */
            private int lapNum = 0;
            /** Elapsed time at end of last lap. */
            private long lastLapTime = 0;

            /** Returns elapsed time in milliseconds.
             *@return The elapsed time
             */
            private long elapsedTime() {
                return prevElapsed +
                        (going ? new Date().getTime() - startDate.getTime() : 0);
            }
            /** Changes the number of elapsed milliseconds into a string.
             *@param time Number of elapsed milliseconds
             *@return The elapsed time as a string.
             */
            private String msToString(long time) {
                String ms, sec, min;
                if (time % 10 >= 5) //round to nearest hundredth
                    time += 5;
                ms = Long.toString(time % 1000);
                while (ms.length() < 3)
                    ms = "0" + ms;
                ms = ms.substring(0, ms.length() - 1);
                time /= 1000;
                sec = Long.toString(time % 60);
                if (sec.length() == 1) sec = "0" + sec;
                time /= 60;
                min = Long.toString(time);
                return min + ":" + sec + "." + ms;
            }

            public void go() {
                startDate = new Date();
                going = true;
            }
            public void noGo() {
                prevElapsed = elapsedTime();
                going = false;
            }
            public void reset() {
                going = false;
                prevElapsed = 0;
                lastLapTime = 0;
            }
            public void addLap() {
                long elapsed = elapsedTime();
                lstLaps.add("冲线 " + Integer.toString(++lapNum)+ " -- " +
                        "用时: " + msToString(elapsed) + " -- " +
                        "冲线时间: " + msToString(elapsed - lastLapTime));
                lastLapTime = elapsed;
            }
            /** Resets the lap list.
             */
            public void resetLap() {
                lstLaps.removeAll();
                lapNum = 0;
                lastLapTime = 0;
            }
            /** Main code of the thread.
             */
            public void run() {
                while (true) {
                    lblWatch.setText(msToString(elapsedTime()));
                    yield();
                }
            }
        }

        public void init() {
            setLayout(new GridLayout(2,1));
            setBackground(Color.lightGray);
            setForeground(Color.black);
            pnlTop.setLayout(new GridLayout(4,4));
            pnlTop.add(new Label("日期:"));
            pnlTop.add(lblDate);
            pnlTop.add(new Label("时间:"));
            pnlTop.add(lblTime);
            pnlTop.add(new Label("计时:"));
            //lblWatch.setBackground(Color.black);
            lblWatch.setForeground(Color.blue);
            pnlTop.add(lblWatch);
            pnlTop.add(btnGo);
            btnGo.setBackground(Color.green);
            pnlTop.add(btnReset);
            pnlTop.add(new Label("定点:"));
            pnlTop.add(lblSplit);
            pnlTop.add(btnSplit);
            pnlTop.add(btnSplitReset);
            pnlTop.add(new Label("冲线时间:"));
            pnlTop.add(new Label());
            pnlTop.add(btnLapAdd);
            pnlTop.add(btnLapReset);
            pnlBot.setLayout(new GridLayout(1,1));
            pnlBot.add(lstLaps);
            add(pnlTop);
            add(pnlBot);
            btnGo.addActionListener(new btnGoListener());
            btnReset.addActionListener(new btnResetListener());
            btnSplit.addActionListener(new btnSplitListener());
            btnSplitReset.addActionListener(new btnSplitResetListener());
            btnLapAdd.addActionListener(new btnLapAddListener());
            btnLapReset.addActionListener(new btnLapResetListener());
            swThread.setDaemon(true);
            ucThread.setDaemon(true);
            swThread.start();
            ucThread.start();
        }

        public static void main(String[] args) {
            Clock applet = new Clock();
            Frame aFrame = new Frame("计时器");
            aFrame.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });
            aFrame.add(applet, BorderLayout.CENTER);
            aFrame.setSize(400, 200);
            applet.init();
            applet.start();
            aFrame.setVisible(true);
        }

    }
